import Vue from "vue";
import Router from "vue-router";
import Layout from "@/layout";
import db from "utils/localstorage/main.js";
import request from "@/utils/request";
import store from "@/store/index.js";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import LocalRouters from "./routers";
import { deepCopy } from "@/utils/assist.js";

// 导入 动态表格列 全局储存管理对象 目的是为了实现一次初始化
import { dynamicTableColGlobalManager } from "components/VTable/classes/DynamicTableColGlobalManage.js";

/**
 * 报错
 * Redirected when going from "/login" to "/dashboard" via a navigation guard.
 *
 * 参考资料 https://www.cnblogs.com/zyh2333/p/14714031.html
 */
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) {
    return originalPush.call(this, location, onResolve, onReject);
  }
  return originalPush.call(this, location).catch((err) => err);
};

Vue.use(Router);

const constRouter = [
  {
    path: "/redirect",
    component: Layout,
    hidden: true,
    children: [
      {
        path: "/redirect/:path*",
        component: (resolve) => require(["@/views/redirect/index"], resolve),
      },
    ],
  },
  {
    path: "/404",
    component: (resolve) => require(["@/views/error-page/404"], resolve),
    hidden: true,
  },
  {
    path: "/login",
    name: "登录页",
    component: (resolve) => require(["@/views/login/index"], resolve),
  },
  {
    path: "/login-sg",
    name: "登录页sg",
    component: (resolve) => require(["@/views/login-sg/login-sg"], resolve),
  },
  {
    path: "/login-third",
    name: "第三方登录页",
    component: (resolve) => require(["@/views/login-third/login-third"], resolve),
  },
  // 2023-12-08 微前端对接问题，生产环境需要将根目录 / 调整为login-third页面
  // {
  //   path: "/",
  //   name: "第三方登录页",
  //   component: (resolve) => require(["@/views/login-third/login-third"], resolve),
  // },
  {
    path: "/",
    component: Layout,
    redirect: "/dashboard",
    children: [
      {
        path: "dashboard",
        component: (resolve) => require(["@/views/dashboard/index"], resolve),
        name: "Dashboard",
        meta: { title: "dashboard", icon: "dashboard", affix: true },
      },
    ],
  },
  {
    path: "/profile",
    component: Layout,
    redirect: "/profile/index",
    hidden: true,
    children: [
      {
        path: "index",
        component: (resolve) => require(["@/views/profile/index"], resolve),
        name: "Profile",
        meta: { title: "profile", icon: "user", noCache: true },
      },
    ],
  },
  {
    path: "/error",
    component: Layout,
    redirect: "noRedirect",
    name: "ErrorPages",
    meta: {
      title: "errorPages",
      icon: "404",
    },
    children: [
      {
        path: "404",
        component: (resolve) => require(["@/views/error-page/404"], resolve),
        name: "Page404",
        meta: { title: "page404", noCache: true },
      },
    ],
  },
];

/** 创建路由实例的函数 */
function createRouter() {
  return new Router({
    scrollBehavior: () => ({
      y: 0,
    }),
    routes: constRouter,
  });
}

/**
 * 重置注册的路由导航map
 * @description
 * 主要是为了通过 `addRoutes` 方法动态注入新路由时，避免重复注册相同 `name` 路由
 *
 * 这是专门针对于 `vue-router3` 的处理方式。
 */
function resetRouter() {
  const newRouter = createRouter();
  router && (router.matcher = newRouter.matcher);
}

const router = createRouter();
// 2023-12-08 生产环境需要打开以下注释，因为微前端主应用打开子应用是默认进入到跟路径下的
// const whiteList = ["/", "/login"];
// 以下是测试环境配置
const whiteList = ["/login", "/login-third"];
let asyncRouter;

/**
 * 添加各个系统的，各个非侧边栏页面的路由。
 * @author 技术运维中心 阮中楠
 * @description
 * 如果相关的业务代码内，需要添加`非侧边栏页面`的路由，需要在此处添加。
 *
 * 这个设计并不好，未来再移除掉。同样的，对应的业务项目也会同步重构相关的业务逻辑；
 */
function addSystemsRouter() {}

/** 初始化一次动态表格列管理对象 */
function initDynamicTableColGlobalManager() {
  dynamicTableColGlobalManager.initStore();
}

/**
 * 形参路由是否属于全局无系统页面路由？
 * @author 技术运维中心 阮中楠
 * @param { import("vue-router").Route } to 路由对象
 */
function isGlobalNoSystemRouter(to) {
  // 一般默认不是这种特殊的路由。这种路由仅仅存在于极少数特殊的页面内。
  let res = false;
  const flag = to.meta.isGlobalNoSystemRouter;
  if (!!flag && flag === true) {
    res = true;
  }
  return res;
}

/**
 * 检查每一个路由，获得当前所选系统的数值
 * @author 技术运维中心 阮中楠
 * @param { import("vue-router").Route } to 路由对象
 * @description
 * 算法：for循环查询父级。可能性能低效。
 *
 * 未来可能的 bug ：某些页面内可能会出现：无论怎么点击，都会只跳转到首页。
 * 那可能是因为查询父级失败，默认返回首页。请检查非侧边栏路由的一级路由是否配置正确。
 *
 * 适用情况：适用于绝大多数有明确系统归属的路由。
 * 全部的后端权限路由都符合情况。因为全部的路由都满足归属于指定系统的需求。
 * 几乎全部的非侧边栏路由符合情况。因为大部分的路由都配置了父级路由为系统路由，满足要求。
 *
 * 无法处理的情况：
 * 不属于任何归属系统的路由。查询父级的时候无法查询到，或者跳转错误。
 */
function getSystemChoiceNumberByEveryRouterPath(to) {
  /** 目标查询路径 这个路径应该是被查出是后端权限路由的一级路由 */
  let targetPath = "";
  /** 父级路由 由子路由查询得 */
  let parentRouter = {};
  /** 被选择的系统编号，并作为函数返回值。默认为0，即为系统首页。该值储存时默认为字符串。 */
  let resSysIndex = "0";

  // 只要当前路由所匹配项不为空，即可以查得到父级路由。
  if (to.matched.length !== 0) {
    // 那么就将第一个元素赋值给父级路由。按照查询结果，第一个元素为父级路由。
    // 值得注意的是，可能查询不到。这个部分在未来很可能会出bug。
    parentRouter = to.matched[0];
    // 获得目标路由路径。
    targetPath = parentRouter.path;
  }

  for (let i = 0; i < asyncRouter.length; i++) {
    if (asyncRouter[i].path === targetPath) {
      // 遍历权限路由。如果找到了路径，就赋值。
      resSysIndex = String(i);
    }
  }

  return resSysIndex;
}

function go(to, next) {
  asyncRouter = filterAsyncRouter(asyncRouter);

  /** 在添加路由之前 重设全部的路由对象 */
  resetRouter();

 router.addRoutes(asyncRouter);
 router.addRoutes(LocalRouters);
  // 添加全部的，和业务系统相关的非侧边栏页面路由配置。
  addSystemsRouter();

  //2023.12.12新增：自动跳转到最底层一级可展示页面， 比如路由是/jcfx，则跳到/jcfx/risk/resource/shelter
  let redirect_path = findFirstRouterPathByRouterName(to.path)
  // console.log("redirect_path", redirect_path)

  next({
    ...to,
    path: redirect_path,
    replace: true,
  });
}

function save(name, data) {
  localStorage.setItem(name, JSON.stringify(data));
}

function get(name) {
  return JSON.parse(localStorage.getItem(name));
}

function filterAsyncRouter(routes) {
  return routes.filter((route) => {
    const component = route.component;
    if (component) {
      if (route.component === "Layout") {
        route.component = Layout;
      } else {
        route.component = view(component);
      }
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children);
      }
      return true;
    }
  });
}

function view(path) {
  return (resolve) => require([`@/views/${path}.vue`], resolve);
}

/**
 * 
 * @param {*} routerObj 
 * @returns 
 */
function getPath(routerObj) {
  while (routerObj.children) {
    routerObj = routerObj.children[0];
  }
  return routerObj.path;
}
/**
 * 2023.12.12新增：按最顶级菜单名，查找这个菜单下的第一个路由，比如jcfx，则找到/jcfx/risk/resource/shelter
 * @param {*} toPath 
 */
function findFirstRouterPathByRouterName(toPath) {
  if(toPath.split('/').length > 2) {
    // 如果已经是这种格式/jcfx/risk/resource/shelter，则不需处理
    return toPath
  }
  let router = get("USER_ROUTER")
  let now_menu_router = {}
  // console.log("router", router)
  for(let item of router) {
    if(item.path == toPath) {
      now_menu_router = item
      break
    }
  }

  while (now_menu_router.children) {
    now_menu_router = now_menu_router.children[0];
  }
  console.log("now_menu_router", now_menu_router)
  return now_menu_router.path;
}

/**
    * 隐藏左侧菜单栏
   */
function setLeftMenuHidden(to){
  console.log('===to',to)
  if(to.query.leftMenuHidden=='1'){
    store.commit("setting/setMenuHidden", true);
    return
  }
  if(to.path == '/dashboard'){
    store.commit("setting/setMenuHidden", true);
    return
  }
  store.commit("setting/setMenuHidden", false);
}

// 导航守卫，渲染动态路由
router.beforeEach((to, from, next) => {
  NProgress.start();
  console.log("to.path", to.path);
  if (whiteList.indexOf(to.path) !== -1) {
    console.log("indexOf(to.path) !== -1");
    next();
  } else {
    const token = db.get("ACCESS_TOKEN");
    const user = db.get("USER");
    const userRouter = get("USER_ROUTER");
    if (token.length && user) {
      if (!asyncRouter) {
        if (!userRouter) {
          request.get(`system/menu/${user.username}`).then((res) => { 
            const permissions = res.data.permissions;
            store.commit("account/setPermissions", permissions);
            asyncRouter = res.data.routes;
            store.commit("account/setRoutes", asyncRouter);
            save("USER_ROUTER", asyncRouter);

            // 初始化动态表格列储存对象
            initDynamicTableColGlobalManager();

            go(to, next);
          });
        } else {
          asyncRouter = userRouter;
          go(to, next);
        }
      } else {
        /**
         * 在正常的路由下，再次检查。当前的路由是否是特殊的全局无系统页面路由？
         * 如果是，则不标记所属系统的编号值。如果否，则继续正常的系统值求取。
         *
         * 当跳过系统值的获取时，此时侧边栏和顶部导航栏的系统值仍旧是之前的值。
         * 这种情况下，很可能会出现新的bug。
         */
        if (!isGlobalNoSystemRouter(to)) {
          // 开始查询系统所选值，并保存。
          let systemChoiceNumber = getSystemChoiceNumberByEveryRouterPath(to);
          store.commit(
            "systemChoice/setSystemChoiceNumber",
            systemChoiceNumber
          );
        }
        setLeftMenuHidden(to)
        next();
      }
    } else {
      if (to.path === "/login") {
        next();
      }else {
        if (window.__MICRO_APP_ENVIRONMENT__) {
          console.log('在微前端环境中')
          window.microApp.dispatch({type: 'LOGOUT'})
          return
        }
        next("/login");
        NProgress.done();
      }
    }
  }
});

router.afterEach((to, from) => {
  if (to.path === "/login") {
    asyncRouter = null;
  }
  NProgress.done();
});

export default router;
